home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / basic / qbcref.com / QBCREF.BAS < prev    next >
Encoding:
BASIC Source File  |  1990-04-30  |  20.5 KB  |  794 lines

  1. '----------------------------------------------------------------------------
  2. 'Program: QBCREF
  3. 'Purpose: Basic Cross Reference Program
  4. 'Author : Greg Tesch
  5. 'History: 27-Dec-1989 Initial Version 1.00
  6. '       : 15-Jan-1989 V 1.10 (Macro Calls)
  7. '       : 18-Jan-1989 V 1.20 (New BldIdent)
  8. '       : 14-Apr-1990 V 1.21 (Fix Stmt Xref Problems)
  9. '       : 29-Apr-1990 V 1.22 (CTRL/C Trap Routine)
  10. '----------------------------------------------------------------------------
  11. REM $STATIC                                 ' STATIC Array Allocation
  12. DEFINT A-Z
  13. '
  14. '   Global Constants
  15. '
  16. CONST Version = "1.22"
  17. CONST FALSE = 0, TRUE = NOT FALSE
  18. CONST WideSize = 96                         ' Width of Listing when /W
  19. CONST NULL$ = ""                            ' Null String
  20. CONST NUL = 0                               ' Null Value
  21. CONST MaxTokenSz = 40                       ' Maximum Token Size
  22. CONST MaxNode = 1000                        ' Maximum Token Elements
  23. CONST DefLines = 60                         ' Default line count
  24. CONST DefTab = 4                            ' Default Tab size
  25. CONST Ident = 1, Literal = 2, Label = 3     ' Token Types
  26. '
  27. '   Global Type Definitions
  28. '
  29. TYPE TokenNode                              ' Token Table Element
  30.     Left AS INTEGER                         ' Left Element Number
  31.     Right AS INTEGER                        ' Rigth Element Number
  32.     Flag AS STRING * 1                      ' Key   Word Flag
  33.     Token AS STRING * MaxTokenSz            ' Stored Token
  34. END TYPE
  35.  
  36. TYPE StackNode                              ' Stack Table Element
  37.     NodeLink AS INTEGER                     ' Element in Token Table
  38.     StackLink AS INTEGER                    ' Next Element In Stack
  39. END TYPE
  40. '
  41. '   Declare External Functions and Subs
  42. '
  43. DECLARE FUNCTION CkKeyWd (Arg AS STRING)
  44. DECLARE FUNCTION NodeCmp (Token AS STRING, SEG Node AS TokenNode)
  45. DECLARE SUB SetCtrlC ()
  46. '
  47. '   Declare Basic Functions and Subs
  48. '
  49. DECLARE FUNCTION Abort ()
  50. DECLARE FUNCTION HaveCmdParams ()
  51. DECLARE FUNCTION IsKeyWord ()
  52. DECLARE FUNCTION InclStmt ()
  53. DECLARE FUNCTION IsSpecial (NextWord AS STRING)
  54. DECLARE FUNCTION GetToken (CurPos AS INTEGER, EndPos AS INTEGER)
  55. DECLARE SUB BldIdent (StartPos AS INTEGER, EndPos AS INTEGER)
  56. DECLARE SUB BldLiteral (StartPos AS INTEGER, EndPos AS INTEGER)
  57. DECLARE SUB BldLabel (StartPos AS INTEGER, EndPos AS INTEGER)
  58. DECLARE SUB InsertToken (Node AS INTEGER)
  59. DECLARE SUB ChkForSpcl (CurPos AS INTEGER, EndPos AS INTEGER)
  60. DECLARE SUB ChkForInclude (StartPos AS INTEGER, EndPos AS INTEGER)
  61. DECLARE SUB CrossRef ()
  62. DECLARE SUB CreateNode (Node AS INTEGER)
  63. DECLARE SUB AnalyzeToken (SkipFlag AS INTEGER)
  64. DECLARE SUB ListToken (Node AS INTEGER)
  65. DECLARE SUB ShowUsage ()
  66. DECLARE SUB Traverse ()
  67. DECLARE SUB FormatOut ()
  68. DECLARE SUB Titles (SubTitle AS STRING)
  69. DECLARE SUB PrintList ()
  70. '
  71. '   Adjust Stack Size for Recursive (SUBS/FUNCS)
  72. '
  73. CLEAR , , 4096
  74. '
  75. '   Global Variable Definitions
  76. '
  77. DIM SHARED InFileName AS STRING             ' Input File Name
  78. DIM SHARED Infile AS INTEGER                ' Input File Number
  79. DIM SHARED ProgName AS STRING               ' Program Name without PATH
  80. DIM SHARED OutFileName AS STRING            ' Output File Name
  81. DIM SHARED OutFile AS INTEGER               ' Output File Number
  82. DIM SHARED InclFile AS INTEGER              ' Current Include File Number
  83. DIM SHARED ListLine AS INTEGER              ' Current Listing Line Number
  84. DIM SHARED ListWidth AS INTEGER             ' Listing Width
  85. DIM SHARED PageNbr AS INTEGER               ' Current Page Number on List
  86. DIM SHARED StmtLen AS INTEGER               ' Length of Current Statement
  87. DIM SHARED CurrStmt AS INTEGER              ' Current Statement Line Number
  88. DIM SHARED TabSize AS INTEGER               ' Number of Chars per TAB
  89. DIM SHARED LinesOnPage AS INTEGER           ' Number of Lines Per Page
  90. DIM SHARED WideList AS INTEGER              ' True If Wide Listing
  91. DIM SHARED WideOn AS STRING * 2             ' Enable Wide List on PRN
  92.     WideOn = CHR$(27) + "M"
  93. DIM SHARED WideOff AS STRING * 2            ' Disable Wide List on PRN
  94.     WideOff = CHR$(27) + "@"
  95. DIM SHARED KeyWords AS INTEGER              ' True If KeyWords To Print
  96. DIM SHARED ListOnly AS INTEGER              ' True If Listing Only
  97. DIM SHARED CrefOnly AS INTEGER              ' True If Cross Reference Only
  98. DIM SHARED Include AS INTEGER               ' True If $INCLUDE: processing
  99. DIM SHARED ErrFlag AS INTEGER               ' Global Error Flag
  100. DIM SHARED TokenType AS INTEGER             ' Current Token Type
  101. DIM SHARED WasGo AS INTEGER                 ' True If last KeyWord was GOTO
  102. DIM SHARED HaveKeyWd AS INTEGER             ' True If KeyWord Found
  103. DIM SHARED NextNode AS INTEGER              ' Next Element in Token Tree
  104. DIM SHARED RootNode AS INTEGER              ' Root Element in Token Tree
  105. DIM SHARED Nodes AS INTEGER                 ' Number of Nodes to Allocate
  106. DIM SHARED Top AS INTEGER                   ' Top Of Stack Pointer
  107. DIM SHARED CurrNode AS INTEGER              ' Current Node To Process
  108. DIM SHARED StackPtr AS INTEGER              ' Current Stack Pointer
  109. DIM SHARED Remark AS INTEGER                ' True if Remark Being Processed
  110. DIM SHARED CrefType AS INTEGER              ' Type Of Cross Ref To Print
  111. DIM SHARED LabelPos AS INTEGER              ' Next Position for A label
  112. DIM SHARED Token AS STRING * MaxTokenSz     ' Current Token Being Processed
  113. DIM SHARED Stmt AS STRING                   ' Current Source Statement
  114. '
  115. '   Global Array Definitions
  116. '
  117. DIM SHARED Stack(1 TO MaxNode) AS StackNode ' Traversed Tree Node Stack
  118. '
  119. '   Main Program
  120. '
  121. PRINT "MAT Enterprises, BASIC Cross Reference Utility  Version "; Version
  122.  
  123. ON ERROR GOTO ErrorHandler
  124.  
  125. IF NOT HaveCmdParams THEN
  126.     CALL ShowUsage
  127. ELSE
  128.     DIM SHARED Tokens(1 TO Nodes) AS TokenNode      ' Tokens Binary Tree
  129.     DIM SHARED Refs(1 TO Nodes) AS STRING           ' Token Line References
  130.     ErrFlag = IsSpecial(Token)                      ' Initialize Tables
  131.     CALL SetCtrlC
  132.     CALL CrossRef
  133.     END
  134. END IF
  135.  
  136. '
  137. '   Error Handler For LoadSrc FUNCTION
  138. '
  139. ErrorHandler:
  140.     CONST FileNotFound = 53
  141.  
  142.     ErrFlag = TRUE
  143.     IF ERR = FileNotFound AND ERL = 1000 THEN RESUME NEXT
  144.     IF ERR = FileNotFound THEN
  145.         PRINT InFileName; " File Not Found"
  146.         RESUME NEXT
  147.     END IF
  148.     ON ERROR GOTO 0
  149.  
  150. '
  151. ' KeyWords With More Than One Part
  152. '
  153. DATA /CALL/"[ ABSOLUTE| INTERRUPT|]"
  154. DATA /COM/"[ ON| OFF| STOP|]"
  155. DATA /DEF/"[ SEG| FN|]"
  156. DATA /END/"[ DEF| FUNCTION| IF| SELECT| SUB| TYPE|]"
  157. DATA /INPUT/"[ #|]"
  158. DATA /KEY/"[ ON| OFF| STOP|]"
  159. DATA /LINE/"[ INPUT|]"
  160. DATA /ON/"[ COM| KEY| PEN| PLAY| STRIG| TIMER| UEVENT| ERROR| GOSUB| GOTO|]"
  161. DATA /OPEN/"[ COM|]"
  162. DATA /OPTION/"[ BASE|]"
  163. DATA /PEN/"[ ON| OFF| STOP|]"
  164. DATA /PLAY/"[ ON| OFF| STOP|]"
  165. DATA /PRINT/"[ #| USING|]"
  166. DATA /RESUME/"[ NEXT|]"
  167. DATA /SELECT/"[ CASE|]"
  168. DATA /STRIG/"[ ON| OFF| STOP|]"
  169. DATA /TIMER/"[ ON| OFF| STOP|]"
  170. DATA /UEVENT/"[ ON| OFF| STOP|]"
  171. DATA ""
  172.  
  173. FUNCTION Abort
  174. PRINT : PRINT "Program Aborted..."
  175. Abort = TRUE
  176. END
  177. END FUNCTION
  178.  
  179. REM $DYNAMIC
  180. SUB AnalyzeToken (SkipFlag AS INTEGER) STATIC
  181.  
  182. IF (Remark AND (LEFT$(Token, 1) <> "$")) THEN
  183.     SkipFlag = TRUE
  184. ELSE
  185.     SELECT CASE TokenType
  186.         CASE Ident
  187.             IF NOT HaveKeyWd THEN HaveKeyWd = IsKeyWord
  188.             IF NOT ListOnly THEN
  189.                 IF KeyWords THEN
  190.                     CALL InsertToken(RootNode)
  191.                 ELSE
  192.                     IF NOT HaveKeyWd THEN CALL InsertToken(RootNode)
  193.                 END IF
  194.             END IF
  195.             IF HaveKeyWd THEN
  196.                 SELECT CASE RTRIM$(Token)
  197.                     CASE "GOTO", "GOSUB", "RESUME", "THEN", "ELSE"
  198.                         WasGo = TRUE
  199.                     CASE "DATA"
  200.                         WasGo = FALSE
  201.                         SkipFlag = TRUE
  202.                     CASE "REM"
  203.                         WasGo = FALSE
  204.                         Remark = TRUE
  205.                     CASE ELSE
  206.                         WasGo = LEFT$(Token, 2) = "ON"
  207.                 END SELECT
  208.             END IF
  209.         CASE Label
  210.             IF NOT ListOnly THEN CALL InsertToken(RootNode)
  211.     END SELECT
  212. END IF
  213.  
  214. END SUB
  215.  
  216. SUB BldIdent (StartPos AS INTEGER, EndPos AS INTEGER) STATIC
  217.  
  218. CONST Valids = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&-"
  219.  
  220. FOR EndPos = StartPos TO StmtLen
  221.     IF INSTR(1, Valids, UCASE$(MID$(Stmt, EndPos, 1))) = 0 THEN EXIT FOR
  222. NEXT EndPos
  223.  
  224. Token = MID$(Stmt, StartPos, EndPos - StartPos)
  225. CALL ChkForSpcl(StartPos, EndPos)
  226. TokenType = Ident
  227. WasGo = (EndPos <= LabelPos)
  228. END SUB
  229.  
  230. SUB BldLabel (StartPos AS INTEGER, EndPos AS INTEGER) STATIC
  231.  
  232. STATIC Ch AS STRING * 1
  233. CONST Terminators = " :,    "
  234.  
  235. IF ((WasGo) OR (StartPos = 1)) AND (StartPos >= LabelPos) THEN
  236.     TokenType = Label
  237.     FOR EndPos = StartPos TO StmtLen
  238.         Ch = MID$(Stmt, EndPos, 1)
  239.         IF INSTR("0123456789", Ch) = 0 THEN
  240.             IF INSTR(1, Terminators, Ch) = 0 THEN TokenType = NUL
  241.             EXIT FOR
  242.         END IF
  243.     NEXT EndPos
  244.     IF TokenType THEN RSET Token = MID$(Stmt, StartPos, EndPos - StartPos)
  245. ELSE
  246.     EndPos = StartPos + 1
  247. END IF
  248.  
  249. END SUB
  250.  
  251. SUB BldLiteral (StartPos AS INTEGER, EndPos AS INTEGER) STATIC
  252.  
  253. TokenType = Literal
  254.  
  255. FOR EndPos = StartPos + 1 TO StmtLen
  256.     IF INSTR("ABCDEFH0123456789abcdefh", MID$(Stmt, EndPos, 1)) THEN EXIT FOR
  257. NEXT EndPos
  258. END SUB
  259.  
  260. SUB ChkForInclude (StartPos AS INTEGER, EndPos AS INTEGER)
  261.  
  262. STATIC FileName AS STRING
  263.  
  264. IF MID$(Token, 1, 1) = "$" THEN
  265.     IF (RTRIM$(Token) <> "$INCLUDE") THEN EXIT SUB
  266. ELSE
  267.     EXIT SUB
  268. END IF
  269.  
  270. I% = INSTR(EndPos + 1, Stmt, "'") + 1
  271. IF I% = 1 THEN EXIT SUB
  272. L% = INSTR(I%, Stmt, "'")
  273. IF L% = 0 THEN EXIT SUB
  274.  
  275. L% = L% - I%
  276.  
  277. FileName = UCASE$(MID$(Stmt, I%, L%))
  278. I% = FREEFILE
  279.  
  280. 1000  OPEN FileName FOR INPUT AS #I%            'Trap if Error
  281.  
  282. IF ErrFlag THEN
  283.     IF CrefOnly THEN PRINT
  284.     PRINT "$INCLUDE: '"; FileName; "' Not Found"
  285.     IF CrefOnly THEN PRINT ProgName; "(";
  286. ELSE
  287.     InclFile = I%
  288.     EndPos = StmtLen
  289. END IF
  290.  
  291. END SUB
  292.  
  293. SUB ChkForSpcl (CurPos AS INTEGER, EndPos AS INTEGER) STATIC
  294.  
  295. STATIC TmpTok AS STRING
  296. STATIC NextWord AS STRING
  297. STATIC LastPos AS INTEGER
  298. STATIC SrchStr AS STRING
  299. STATIC NextPos AS INTEGER
  300. STATIC Length AS INTEGER
  301.  
  302. TmpTok = UCASE$(RTRIM$(Token))
  303.  
  304. IF NOT IsSpecial(NextWord) THEN
  305.     EXIT SUB
  306. ELSE
  307.     HaveKeyWd = FALSE
  308. END IF
  309.  
  310. LastPos = INSTR(CurPos, Stmt, CHR$(&H22))
  311. LabelPos = INSTR(CurPos, Stmt, "'")
  312. IF LabelPos < LastPos THEN LastPos = LabelPos
  313. LabelPos = INSTR(CurPos, Stmt, ":")
  314. IF LabelPos < LastPos THEN LastPos = LabelPos
  315. IF LastPos = 0 THEN LastPos = StmtLen
  316. NextPos = 1
  317.  
  318. DO
  319.     NextPos = INSTR(NextPos, NextWord, " ")
  320.     IF NextPos THEN
  321.         Length = INSTR(NextPos, NextWord + "|", "|") - NextPos
  322.         SrchStr = MID$(NextWord, NextPos, Length)
  323.         LabelPos = INSTR(EndPos, Stmt, SrchStr)
  324.         IF LabelPos AND LabelPos < LastPos THEN
  325.             TmpTok = TmpTok + SrchStr
  326.             HaveKeyWd = TRUE
  327.             IF (SrchStr <> " FN") THEN
  328.                 MID$(Stmt, LabelPos, Length) = SPACE$(Length)
  329.             END IF
  330.         END IF
  331.         NextPos = NextPos + Length - 1
  332.     END IF
  333. LOOP WHILE NextPos AND NOT HaveKeyWd
  334.  
  335. Token = TmpTok
  336. END SUB
  337.  
  338. SUB CreateNode (Node AS INTEGER) STATIC
  339.  
  340. IF (NextNode > MaxNode) THEN
  341.     PRINT "Maximum References Reached"
  342.     EXIT SUB
  343. ELSE
  344.     NextNode = NextNode + 1
  345.     Node = NextNode
  346.     IF (RootNode = NUL) THEN RootNode = 1
  347. END IF
  348.  
  349. Tokens(Node).Left = NUL
  350. Tokens(Node).Right = NUL
  351. Tokens(Node).Flag = CHR$(HaveKeyWd AND &HF0 OR TokenType)
  352. Tokens(Node).Token = Token
  353. Refs(Node) = MKI$(CurrStmt)
  354. END SUB
  355.  
  356. SUB CrossRef STATIC
  357.  
  358. STATIC SkipFlag AS INTEGER              ' True if comment active
  359. STATIC TStart AS INTEGER                ' Start Position of Token
  360. STATIC TEnd AS INTEGER                  ' End Position of Token
  361. STATIC Ch AS STRING * 1
  362.  
  363. Infile = FREEFILE
  364. OPEN InFileName FOR INPUT AS #Infile
  365.  
  366. IF ErrFlag THEN EXIT SUB
  367.  
  368. OutFile = FREEFILE                      ' Gen Next File Number
  369. OPEN OutFileName FOR OUTPUT AS OutFile
  370.  
  371. IF ErrFlag THEN
  372.     CLOSE #Infile
  373.     EXIT SUB
  374. END IF
  375.  
  376. IF WideList THEN
  377.     ListWidth = WideSize
  378.     IF OutFileName = "PRN" THEN PRINT #OutFile, WideOn;
  379. ELSE
  380.     ListWidth = 80
  381. END IF
  382.  
  383. WIDTH #OutFile, ListWidth
  384. PageNbr = 0
  385. ListLine = LinesOnPage
  386. CurrStmt = 0
  387. FOR TEnd = LEN(InFileName) TO 1 STEP -1
  388.     Ch = MID$(InFileName, TEnd, 1)
  389.     IF INSTR("\:", Ch) THEN EXIT FOR
  390.     ProgName = Ch + ProgName
  391. NEXT TEnd
  392.  
  393. IF CrefOnly THEN PRINT ProgName; "(";
  394.  
  395. DO WHILE NOT EOF(Infile)
  396.     IF NOT InclStmt THEN LINE INPUT #Infile, Stmt
  397.     IF NOT EOF(Infile) THEN
  398.         LabelPos = 0
  399.         WasGo = FALSE
  400.         CurrStmt = CurrStmt + 1
  401.         StmtLen = LEN(Stmt)
  402.         IF NOT CrefOnly THEN CALL PrintList
  403.         TStart = 1
  404.         TEnd = 1
  405.         Remark = FALSE
  406.         SkipFlag = FALSE
  407.         DO WHILE (TStart <= StmtLen)
  408.             IF GetToken(TStart, TEnd) THEN
  409.                 CALL AnalyzeToken(SkipFlag)
  410.                 IF HaveKeyWd AND Remark THEN
  411.                     CALL ChkForInclude(TStart, TEnd)
  412.                 END IF
  413.             END IF
  414.             IF SkipFlag THEN TStart = StmtLen + 1 ELSE TStart = TEnd + 1
  415.         LOOP
  416.         IF CrefOnly THEN
  417.             IF (CurrStmt MOD 10 = 0) THEN
  418.                 X$ = LTRIM$(STR$(CurrStmt))
  419.                 PRINT X$; ")";
  420.                 LOCATE , POS(0) - LEN(X$) - 1
  421.             END IF
  422.         END IF
  423.     END IF
  424. LOOP
  425.  
  426. CLOSE #Infile
  427. CALL FormatOut
  428. END SUB
  429.  
  430. SUB FormatOut STATIC
  431.  
  432. IF NOT ListOnly THEN
  433.     ListLine = LinesOnPage
  434.     FOR CrefType = 1 TO 2
  435.         Top = NUL                               ' Make TOP of Stack NUL
  436.         StackPtr = NUL
  437.         CurrNode = RootNode                     ' Start With Root Node
  438.         IF (KeyWords) OR (CrefType = 2) THEN CALL Traverse
  439.     NEXT CrefType
  440. END IF
  441.  
  442. IF OutFileName = "PRN" THEN
  443.     IF PageNbr THEN PRINT #OutFile, CHR$(12);
  444.     PRINT #OutFile, WideOff;
  445. END IF
  446.  
  447. CLOSE #OutFile
  448. END SUB
  449.  
  450. FUNCTION GetToken (CurPos AS INTEGER, EndPos AS INTEGER) STATIC
  451.  
  452. TokenType = NUL
  453. HaveKeyWd = FALSE
  454. GetToken = TRUE
  455.  
  456. FOR CurPos = CurPos TO StmtLen
  457.     SELECT CASE ASC(MID$(Stmt, CurPos, 1))
  458.         CASE 65 TO 90, 97 TO 122                    '"A" TO "Z", "a" to "z"
  459.             CALL BldIdent(CurPos, EndPos)
  460.             EXIT FUNCTION
  461.         CASE 48 TO 57                               '"0" TO "9"
  462.             CALL BldLabel(CurPos, EndPos)
  463.             EXIT FUNCTION
  464.         CASE &H22                                   '"
  465.             CurPos = INSTR(CurPos + 1, Stmt, CHR$(&H22))
  466.             IF CurPos = 0 THEN CurPos = StmtLen
  467.         CASE 38                                     '"&"
  468.             CALL BldLiteral(CurPos, EndPos)
  469.             EXIT FUNCTION
  470.         CASE 36                                     '"$"
  471.             IF Remark THEN
  472.                 CALL BldIdent(CurPos, EndPos)
  473.                 EXIT FUNCTION
  474.             END IF
  475.         CASE 39                                     '"'"
  476.             Remark = TRUE
  477.     END SELECT
  478. NEXT CurPos
  479. EndPos = CurPos
  480. GetToken = FALSE
  481. END FUNCTION
  482.  
  483. FUNCTION HaveCmdParams
  484.  
  485. LinesOnPage = DefLines
  486. TabSize = DefTab
  487. Nodes = MaxNode
  488. Include = FALSE
  489.  
  490. C$ = RTRIM$(LTRIM$(COMMAND$))
  491.  
  492. DO WHILE C$ <> NULL$
  493.     I% = INSTR(C$ + " ", " ")
  494.     IF I% THEN
  495.         P$ = LEFT$(C$, I% - 1)
  496.         C$ = LTRIM$(MID$(C$, I% + 1))
  497.         IF InFileName = NULL$ THEN
  498.             InFileName = P$
  499.             IF INSTR(P$, ".") = 0 THEN InFileName = InFileName + ".BAS"
  500.             HaveCmdParams = TRUE
  501.         ELSE
  502.             IF LEFT$(P$, 1) <> "/" AND LEFT$(P$, 1) <> "-" THEN
  503.                 PRINT "Illegal Option "; P$
  504.                 HaveCmdParams = FALSE
  505.                 EXIT FUNCTION
  506.             END IF
  507.  
  508.             SELECT CASE MID$(P$, 2, 1)
  509.                 CASE "C"
  510.                     IF NOT ListOnly THEN
  511.                         CrefOnly = TRUE
  512.                     ELSE
  513.                         PRINT "Conflicting Options /C /L"
  514.                         HaveCmdParams = FALSE
  515.                     END IF
  516.                 CASE "I"
  517.                     Include = TRUE
  518.                 CASE "L"
  519.                     IF NOT CrefOnly THEN
  520.                         ListOnly = TRUE
  521.                     ELSE
  522.                         PRINT "Conflicting Options /C /L"
  523.                         HaveCmdParams = FALSE
  524.                     END IF
  525.                 CASE "K"
  526.                     KeyWords = TRUE
  527.                 CASE "W"
  528.                     WideList = TRUE
  529.                 CASE "O"
  530.                     OutFileName = MID$(P$, 3)
  531.                 CASE "P", "T", "R"
  532.                     I% = VAL(MID$(P$, 3))
  533.                     SELECT CASE MID$(P$, 2, 1)
  534.                         CASE "P"
  535.                             LinesOnPage = I%
  536.                         CASE "T"
  537.                             TabSize = I%
  538.                         CASE "R"
  539.                             Nodes = I%
  540.                     END SELECT
  541.                 CASE ELSE
  542.                     PRINT "Unknown Option "; P$
  543.                     HaveCmdParams = FALSE
  544.             END SELECT
  545.         END IF
  546.     END IF
  547. LOOP
  548.  
  549. IF LinesOnPage = 0 THEN LinesOnPage = DefLines
  550. IF TabSize = 0 THEN TabSize = DefTab
  551. IF Nodes = 0 THEN Nodes = MaxNode
  552. IF OutFileName = NULL$ THEN OutFileName = "PRN"
  553. C$ = NULL$
  554. END FUNCTION
  555.  
  556. FUNCTION InclStmt
  557.  
  558. IF NOT Include THEN
  559.     InclStmt = FALSE
  560.     EXIT FUNCTION
  561. END IF
  562.  
  563. IF InclFile > OutFile THEN
  564.     LINE INPUT #InclFile, Stmt
  565.     IF EOF(InclFile) THEN
  566.         CLOSE #InclFile
  567.         InclFile = InclFile - 1
  568.         InclStmt = InclStmt
  569.     ELSE
  570.         InclStmt = TRUE
  571.     END IF
  572. ELSE
  573.     InclStmt = FALSE
  574. END IF
  575.  
  576. END FUNCTION
  577.  
  578. SUB InsertToken (Node AS INTEGER)
  579.  
  580. IF Node = NUL THEN
  581.     CALL CreateNode(Node)
  582. ELSE
  583.     SELECT CASE NodeCmp(Token, Tokens(Node))
  584.         CASE IS < 0
  585.             CALL InsertToken(Tokens(Node).Left)
  586.         CASE IS > 0
  587.             CALL InsertToken(Tokens(Node).Right)
  588.         CASE ELSE
  589.             Refs(Node) = Refs(Node) + MKI$(CurrStmt)
  590.     END SELECT
  591. END IF
  592. END SUB
  593.  
  594. FUNCTION IsKeyWord
  595.  
  596. STATIC TmpStr AS STRING
  597.  
  598. TmpStr = "/" + UCASE$(RTRIM$(Token)) + "/"
  599. IF CkKeyWd(TmpStr) THEN
  600.     Token = MID$(TmpStr, 2, LEN(TmpStr) - 2)
  601.     IsKeyWord = TRUE
  602. ELSE
  603.     IsKeyWord = FALSE
  604. END IF
  605. END FUNCTION
  606.  
  607. FUNCTION IsSpecial (NextWord AS STRING) STATIC
  608.  
  609. CONST SpclSize = 800
  610.  
  611. STATIC SpclWrds AS STRING * SpclSize
  612. STATIC TmpStr AS STRING
  613. STATIC Indx AS INTEGER
  614. STATIC Length AS INTEGER
  615.  
  616. IF ASC(SpclWrds) = NUL THEN
  617.     Indx = 1
  618.     DO
  619.         READ TmpStr
  620.         IF (TmpStr <> NULL$) THEN
  621.             MID$(SpclWrds, Indx, LEN(TmpStr)) = TmpStr
  622.             Indx = Indx + LEN(TmpStr)
  623.         END IF
  624.     LOOP UNTIL TmpStr = NULL$
  625. END IF
  626.  
  627. IsSpecial = FALSE
  628. Indx = INSTR(SpclWrds, "/" + UCASE$(LEFT$(Token, 1)))
  629. IF Indx THEN
  630.     TmpStr = "/" + UCASE$(RTRIM$(Token)) + "/"
  631.     Indx = INSTR(Indx, SpclWrds, TmpStr)
  632.     IF Indx THEN
  633.         Indx = INSTR(Indx, SpclWrds, "[")
  634.         Length = INSTR(Indx, SpclWrds, "]") - Indx + 1
  635.         NextWord = MID$(SpclWrds, Indx, Length)
  636.         IsSpecial = TRUE
  637.     END IF
  638. END IF
  639. END FUNCTION
  640.  
  641. SUB ListToken (Node AS INTEGER) STATIC
  642.  
  643. CONST FrstRefPos = 20
  644.  
  645. STATIC TStr AS STRING
  646. STATIC Indx AS INTEGER
  647. STATIC CurPos AS INTEGER
  648. STATIC SubTitle AS STRING
  649. STATIC LastType AS INTEGER
  650.  
  651. IF ASC(Tokens(Node).Flag) AND &HF0 THEN
  652.     IF CrefType = 2 THEN EXIT SUB
  653. ELSE
  654.     IF CrefType = 1 THEN EXIT SUB
  655. END IF
  656.  
  657. IF CrefType <> LastType THEN
  658.     LastType = CrefType
  659.     SELECT CASE CrefType
  660.         CASE 1
  661.             SubTitle = "BASIC Keywords"
  662.         CASE 2
  663.             SubTitle = RTRIM$(ProgName) + " References"
  664.     END SELECT
  665.     IF ListLine + 4 < LinesOnPage THEN
  666.         PRINT #OutFile,
  667.         PRINT #OutFile, SubTitle
  668.         PRINT #OutFile,
  669.         ListLine = ListLine + 3
  670.     END IF
  671. END IF
  672.  
  673. CALL Titles(SubTitle)
  674. IF (ASC(Tokens(Node).Flag) AND &HF) = Label THEN
  675.     TStr = RTRIM$(LTRIM$(Tokens(Node).Token))
  676. ELSE
  677.     TStr = RTRIM$(Tokens(Node).Token)
  678. END IF
  679. PRINT #OutFile, TStr; TAB(FrstRefPos);
  680. IF LEN(TStr) >= FrstRefPos THEN ListLine = ListLine + 1
  681. CurPos = FrstRefPos
  682. TStr = Refs(Node)
  683.  
  684. FOR Indx = 1 TO LEN(TStr) STEP 2
  685.     IF (CurPos + 5 > ListWidth) THEN
  686.         PRINT #OutFile,
  687.         CALL Titles(SubTitle)
  688.         CurPos = FrstRefPos
  689.         PRINT #OutFile, TAB(FrstRefPos);
  690.     END IF
  691.     PRINT #OutFile, USING "#### "; CVI(MID$(TStr, Indx, 2));
  692.     CurPos = CurPos + 5
  693. NEXT Indx
  694.  
  695. PRINT #OutFile,
  696. END SUB
  697.  
  698. SUB PrintList STATIC
  699.  
  700. CONST FrstPos = 6
  701.  
  702. STATIC CurPos AS INTEGER
  703. STATIC Ch AS STRING * 1
  704.  
  705. CALL Titles(NULL$)
  706. PRINT #OutFile, USING "#### "; CurrStmt;
  707. CurPos = FrstPos
  708.  
  709. FOR I% = 1 TO StmtLen
  710.     IF (CurPos + 1 > ListWidth) THEN
  711.         PRINT #OutFile,
  712.         CALL Titles(NULL$)
  713.         PRINT #OutFile, TAB(FrstPos);
  714.         CurPos = FrstPos
  715.     END IF
  716.  
  717.     Ch = MID$(Stmt, I%, 1)
  718.     IF (Ch = CHR$(9)) THEN
  719.         J% = TabSize - ((CurPos - FrstPos) MOD TabSize)
  720.         CurPos = CurPos + J%
  721.         DO WHILE (J% > 0)
  722.             PRINT #OutFile, " ";
  723.             J% = J% - 1
  724.         LOOP
  725.     ELSE
  726.         CurPos = CurPos + 1
  727.         PRINT #OutFile, Ch;
  728.     END IF
  729. NEXT I%
  730.  
  731. PRINT #OutFile,
  732. END SUB
  733.  
  734. SUB ShowUsage STATIC
  735.  
  736. PRINT CHR$(10); "Usage: QBCREF FileName [Options]"; CHR$(10)
  737. PRINT "Options : (Separated by Space)"
  738. PRINT "/C      = Cross Reference Only"
  739. PRINT "/I      = Enable $INCLUDE: Metacommand"
  740. PRINT "/L      = Listing Only (Default List & Cref)"
  741. PRINT "/OFile  = Output Filename"
  742. PRINT "/Pnn    = Page Size (Default"; STR$(DefLines); " Lines)"
  743. PRINT "/Rnnnn  = Number of References (Default"; STR$(MaxNode); ")"
  744. PRINT "/K      = Include BASIC Key Words"
  745. PRINT "/Tn     = Tab Size (Default"; STR$(DefTab); ")"
  746. PRINT "/W      = Wide Listing (Default Narrow)"
  747.  
  748. END SUB
  749.  
  750. SUB Titles (SubTitle AS STRING) STATIC
  751.  
  752. STATIC Hdr AS STRING
  753.  
  754. IF PageNbr = 0 THEN
  755.     X$ = "BASIC Cross Reference of " + ProgName
  756.     I% = (ListWidth - LEN(X$) - 18) \ 2
  757.     Hdr = DATE$ + SPACE$(I%) + X$
  758. END IF
  759.  
  760. ListLine = ListLine + 1
  761.  
  762. IF (ListLine >= LinesOnPage) THEN
  763.     ListLine = 0
  764.     PageNbr = PageNbr + 1
  765.     IF (OutFileName = "PRN") AND (PageNbr > 1) THEN PRINT #OutFile, CHR$(12);
  766.     PRINT #OutFile, Hdr; TAB(ListWidth - 8); "Page";
  767.     PRINT #OutFile, USING "###"; PageNbr
  768.     IF SubTitle <> NULL$ THEN PRINT #OutFile, SubTitle
  769.     PRINT #OutFile,
  770. END IF
  771.        
  772. END SUB
  773.  
  774. SUB Traverse
  775.  
  776. DO WHILE (CurrNode <> NUL)
  777.     StackPtr = StackPtr + 1
  778.     Stack(StackPtr).NodeLink = CurrNode
  779.     Stack(StackPtr).StackLink = Top
  780.     Top = StackPtr
  781.     CurrNode = Tokens(CurrNode).Left
  782. LOOP
  783.  
  784. IF (Top <> NUL) THEN
  785.     CurrNode = Stack(Top).NodeLink
  786.     Top = Stack(Top).StackLink
  787.     CALL ListToken(CurrNode)
  788.     CurrNode = Tokens(CurrNode).Right
  789.     Traverse
  790. END IF
  791.  
  792. END SUB
  793.  
  794.